#pragma once
#include <iostream>
#include <sys/epoll.h>
#include <unistd.h>
#include "Log.hpp"
#include "Err.hpp"

static const int size = 64;
static const int defaultfd = -1;

class Epoller
{
public:
    Epoller(int epfd = defaultfd)
        : _epfd(epfd)
    {
    }
    ~Epoller()
    {
        if (_epfd != defaultfd)
        {
            close(_epfd);
        }
    }

public:
    void CreateEpoll()
    {
        _epfd = epoll_create(size);
        if (_epfd < 0)
        {
            logMessage(FATAL, "epoll create fail");
            exit(EPOLL_CREATE_ERR);
        }
        logMessage(NORMAL, "epoll create success");
    }

    bool AddEvents(int sock, uint32_t events)
    {
        struct epoll_event ev;
        ev.events = events;
        ev.data.fd = sock;

        int n = epoll_ctl(_epfd, EPOLL_CTL_ADD, sock, &ev);
        logMessage(DEBUG, "AddEvents success");
        return n == 0; // 成功返回0
    }

    void Close()
    {
        close(_epfd);
    }

    int Wait(struct epoll_event *event, int num, int timeout)
    {
        // 把就绪事件结果捞取上来
        int n = epoll_wait(_epfd, event, num, timeout);
        return n;
    }

    bool Control(int sock, uint32_t events, int action)
    {
        int n = 0;
        if (action == EPOLL_CTL_MOD)
        {
            struct epoll_event ev;
            ev.data.fd = sock;
            ev.events = events;
            n = epoll_ctl(_epfd, EPOLL_CTL_MOD, sock, &ev);
        }
        else if (action == EPOLL_CTL_DEL)
        {
            n = epoll_ctl(_epfd, EPOLL_CTL_DEL, sock, nullptr);
        }
        else 
        {
            n = -1;
        }

        return n == 0;
    }

private:
    int _epfd;
};